package com.hospital.endescryption.module.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hospital.common.core.constants.InsuranceFinal;
import com.hospital.common.core.exception.ExceptionPrint;
import com.hospital.common.core.module.entity.MED.MedRequest;
import com.hospital.common.core.module.entity.NFC.NFCResponse;
import com.hospital.common.core.result.ErrorTip;
import com.hospital.common.core.result.SuccessTip;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.HseEncAndDecUtil;
import com.hospital.common.core.utils.Sm2Demo;
import com.hospital.common.core.utils.Sm3Demo;
import com.hospital.common.core.utils.StrKit;
import com.hospital.endescryption.async.WxPayFunc;
import com.hospital.endescryption.module.entity.EncryptionDecryptionDict;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/encdesc")
public class EncAndDescController {
    @Resource
    private WxPayFunc wxPayFunc;
    @Autowired
    private enctrytionController enctrytionController;

    /**
     * 加解密  支付宝、人保 his调用医保用 sm3签名算法  医保请求his sm2签名算法    均用sm4算法加密
     * 微信移动医保、电子处方上传 签名算法 SM2 (SM3withSM2)  均用sm4算法加密
     *requestVal data 中加密时只需要加密内容，解密时需要所有接口返回原来字符串
     * @param requestVal
     * @return
     */
    @PostMapping(value = "/insurance", produces = {"application/json;charset=UTF-8"})
    public Tip getorgone(@RequestBody NFCResponse requestVal) {
        Tip tip = null;
        String dec=null;
        String enc=null;
        EncryptionDecryptionDict encryptionDecryptionDict = enctrytionController.getBySql(requestVal.getDataType(),requestVal.getChannel(),requestVal.getFromApp(),requestVal.getToApp());
        JSONObject jsonObject = null;
        try {
            Object dataReq = requestVal.getData();
            String string = JSON.toJSONString(dataReq);
            JSONObject sortJson = JSON.parseObject(string);
            JSONObject jsonobjectData = StrKit.getSortJson(sortJson);
            switch (requestVal.getDataType()) {
                case InsuranceFinal.DEC:
                    switch (encryptionDecryptionDict.getSingType()) {
                        case InsuranceFinal.SM2:
                            //sm2验签sm4解密
                            if (requestVal.getChannel().equals(InsuranceFinal.Alipay) || requestVal.getChannel().equals(InsuranceFinal.PeopM)) {
                                tip = wxPayFunc.getLastClass(jsonobjectData, encryptionDecryptionDict.getAppId(),
                                        encryptionDecryptionDict.getAppSecret(),
                                        encryptionDecryptionDict.getPlatformPublicKey());
//                            } else if (requestVal.getChannel().equals(InsuranceFinal.InsurBase)){
//                                String s =   SM2Util.decrypt(SM2Util.getPrivateKey(encryptionDecryptionDict.getHosPrivateKey()),jsonobjectData.toJSONString());
//                                jsonObject = JSON.parseObject(s);
//                                tip = new SuccessTip(jsonObject);
                            }else {
                                //SM2 (SM3withSM2)算法验签sm4解密
                                String s = HseEncAndDecUtil.decryptMsg(jsonobjectData,
                                        encryptionDecryptionDict.getAppSecret(), encryptionDecryptionDict.getPlatformPublicKey(),
                                        encryptionDecryptionDict.getAppId());
                                jsonObject = JSON.parseObject(s);
                                tip = new SuccessTip(jsonObject);
                            }
                            break;
                        default:
                            //sm3验签sm4解密
                            jsonObject = Sm3Demo.denc(jsonobjectData, encryptionDecryptionDict.getAppId(),
                                    encryptionDecryptionDict.getAppSecret());
                            tip = new SuccessTip(jsonObject);
                    }
                    enc=JSON.toJSONString(requestVal.getData());
                    dec=JSON.toJSONString(tip.getData());
                    break;
                default:
                    switch (encryptionDecryptionDict.getSingType()) {
                        case InsuranceFinal.SM2:
                            //sm2签名sm4加密
                            if (requestVal.getChannel().equals(InsuranceFinal.Alipay) || requestVal.getChannel().equals(InsuranceFinal.PeopM)) {
                                jsonObject = getSm2Request(encryptionDecryptionDict, jsonobjectData);
                                tip = new SuccessTip(jsonObject);
//                            } else if (requestVal.getChannel().equals(InsuranceFinal.InsurBase)){
//                                String s =   SM2Util.encrypt(SM2Util.getPublicKey(encryptionDecryptionDict.getPlatformPublicKey()),jsonobjectData.toJSONString());
//                                jsonObject = JSON.parseObject(s);
//                                tip = new SuccessTip(jsonObject);
                            } else {
                                //SM2 (SM3withSM2)算法验签sm4解密
                                String parse = string;
                                jsonObject = HseEncAndDecUtil.encryptMsg(encryptionDecryptionDict.getAppId(),
                                        encryptionDecryptionDict.getAppSecret(), encryptionDecryptionDict.getHosPrivateKey(), "", JSON.parseObject(parse));
                                tip = new SuccessTip(jsonObject);
                            }
                            break;
                        default:
                            //sm3签名sm4加密
                            jsonObject = getSm3Request(jsonobjectData, encryptionDecryptionDict);
                            tip = new SuccessTip(jsonObject);
                    }
                    dec=JSON.toJSONString(requestVal.getData());
                    enc=JSON.toJSONString(tip.getData());
            }
        } catch (Exception e) {
            tip = new ErrorTip(303, e.getMessage());
        } finally {
            ExceptionPrint.printCommErrorString("加密验签解密接口",
                    JSON.toJSONString(requestVal),
                    String.valueOf(tip.getCode())
                    , tip.getMessage(), requestVal.getDataType(), "返回给接口数据：" + JSON.toJSONString(tip),  "", dec, enc);
        }
        return tip;
    }

    /**
     * 获取SM3最终的接口调用类并sm3签名加密
     *
     * @return
     */
    private JSONObject getSm3Request(JSONObject jsonObject, EncryptionDecryptionDict encryptionDecryptionDict) {
        MedRequest medRequest = new MedRequest();
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        medRequest.setTimestamp(String.valueOf(timeInMillis));
        medRequest.setEncryptType(encryptionDecryptionDict.getEncType());
        medRequest.setVersion(encryptionDecryptionDict.getVersion());
        medRequest.setSignType(encryptionDecryptionDict.getSingType());
        medRequest.setAppId(encryptionDecryptionDict.getAppId());
        medRequest.setParam(jsonObject);
        Map<String, String> map = Sm3Demo.encAndSingHis(jsonObject.toJSONString(), JSON.parseObject(JSON.toJSONString(medRequest)),
                encryptionDecryptionDict.getAppId(), encryptionDecryptionDict.getAppSecret());
        medRequest.setEncryptData(map.get(InsuranceFinal.ENCRYPT_DATA));
        medRequest.setSign(map.get(InsuranceFinal.SIGN_DATA));
        medRequest.setParam(null);
        medRequest.setCode(0);
        String string = JSON.toJSONString(medRequest);
        return JSON.parseObject(string);
    }

    /**
     * 获取SM2最终的接口调用类并sm2签名加密
     *
     * @return
     */
    private JSONObject getSm2Request(EncryptionDecryptionDict encryptionDecryptionDict, JSONObject jsonObject) {
        NFCResponse nfcResponse = new NFCResponse();
        nfcResponse.setSignType(encryptionDecryptionDict.getSingType());
        nfcResponse.setEncType(encryptionDecryptionDict.getEncType());
        nfcResponse.setVersion(encryptionDecryptionDict.getVersion());
        nfcResponse.setCode(0);
        nfcResponse.setAppId(encryptionDecryptionDict.getAppId());
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        nfcResponse.setTimestamp(String.valueOf(timeInMillis));
        nfcResponse.setData(jsonObject);
        Map<String, String> map = Sm2Demo.encAndSingRes(jsonObject.toJSONString(), JSON.parseObject(JSON.toJSONString(nfcResponse)),
                encryptionDecryptionDict.getAppId(),
                encryptionDecryptionDict.getAppSecret(), encryptionDecryptionDict.getHosPublicKey(), encryptionDecryptionDict.getHosPrivateKey());
        nfcResponse.setEncData(map.get(InsuranceFinal.ENCRYPT_DATA));
        nfcResponse.setSignData(map.get(InsuranceFinal.SIGN_DATA));
        String string = JSON.toJSONString(nfcResponse);
        return JSON.parseObject(string);
    }

}
